1. /* slfdivkn.cpp by K.Tsuru */
  2. // function ID = 215 DRADIX, BRADIX
  3. /********************************************************************
  4. SLong and SInteger classes
  5. This is a protected member function which user cannot access.
  6. It provides the division and remainder.
  7. q = m/n, r = m - q*n; m and n both positive
  8. It is assumed that the conditions such as m > n > 0, n > 1 have been
  9. checked in the LLDiv(). The Knuth's method is used.
  10. If you made a new program please test by taking
  11. a = 10^15-1 = 99999 99999 99999 (generally R^n-1 with radix R)
  12. b = 10^10-1 = 99999 99999 (id.)
  13. r=a*b; c = r/a;
  14. and check that b == c. The division "r/a" causes an "add back".
  15. **********************************************************************/
  16. #ifndef SN_H
  17. #include "sn.h"
  18. #endif
  19. static const char* func = "KnuthLLDiv";
  20. Ldiv_t SLong::KnuthLLDiv(const SLong& m, const SLong& n, bool needRem){
  21. if( (m.Head() < n.Head()) || (m.Sign() <= 0) || (n.Sign() <= 0) ){
  22. m.SetError(m.SYNTAX_ERR, func, 215);
  23. }
  24. int j, uh, vh;
  25. fType d, qq, v1, v2, rdx = m.Radix();
  26. SLong q(m.Type(), m.Head()+2-n.Head()), u(m); //work area for quotient and remainder
  27. SLong v(n), b1(m.Type(), 0);
  28. //normalization and initialization
  29. d = rdx/( v[v.Head()] +1 );
  30. u = LsMult(u, d); v = LsMult(v,d); //u*=d, v*=d
  31. j = uh = u.Head() + 1;
  32. u.Reserve(j+1); //for calling u(j), u(j) = 0
  33. vh = v.Head();
  34. v1 = v.figure(vh); v2 = v.figure(vh-1); // v1 >= rdx/2
  35. v.ShiftArray(uh - vh-1); // v = v*rdx^(uh-vh-1)
  36. long w, w1;
  37. while( j > vh ){
  38. //It gets a tentative quotient "qq" in one figure by dividing v into u.
  39. w = (long)u.figure(j)*(long)rdx + (long)u.figure(j-1);
  40. qq = (u.figure(j) == v1 ) ? (rdx -1) : fType(w/v1); //error of qq <= 2
  41. w1 = ( w - (long)qq*(long)v1 )*(long)rdx + (long)u.figure(j-2);
  42. while( (long)v2*(long)qq > w1 ){
  43. qq--;
  44. w1 = ( w - (long)qq*(long)v1 )*(long)rdx + (long)u.figure(j-2);
  45. }
  46. u = u - LsMult(v, qq); // u = u - qq*v;
  47. int us = u.Sign(215);
  48. if(us < 0){ //[Add back] u < 0, The probability is less than 2/rdx
  49. // fprintf(stderr, "\"add back\" occurs.\n");
  50. b1.SetLong(1);
  51. b1.ShiftArray(j+1); // b1 = rdx^(j+1)
  52. u += b1; // a complement of b
  53. qq--;
  54. u += v;
  55. u.figure[j+1]=0; //neglect the carry
  56. u.CheckArray(215);
  57. }
  58. q.figure[j - vh -1] = qq;
  59. if(us == 0) break; // added since ver 2.181. Thanks Y.Senda for the suggestion on Dec 5, 2009.
  60. v.ShiftArray(-1); // v /= rdx;
  61. j--;
  62. }
  63. q.SetSign(1);
  64. //It gets the figure positions.
  65. j = uh - vh-1;
  66. while(!q.figure(j)) j--;
  67. q.aHead = j;
  68. j = 0;
  69. while(!q.figure(j)) j++;
  70. q.aTail = j;
  71. q.CutDown(q.POP); //need POP
  72. q.DoCutDown(); //reduce the size if possible
  73. if(!needRem) return q; // Ldiv_t(q, 0.0);
  74. if( u.Sign(215) ){ //remainder!=0
  75. u = LsDiv(u, (ulong)d); u.SetSign(1); //u /= d
  76. }
  77. if( u.Verify() ) {// added since ver 2.181.
  78. SLong v = m - n*q -u;
  79. if( v.Sign(215) != 0) v.SetError(v.FATAL, func, 215);
  80. }
  81. return Ldiv_t(q, u);
  82. }

slmdivkn.cpp : last modifiled at 2017/03/13 14:32:00(3,053 bytes)
created at 2017/10/07 10:26:49
The creation time of this html file is 2017/11/09 14:52:03 (Thu Nov 09 14:52:03 2017).